"""
Utility interfaces for the event system.

This module defines interfaces for serialization, observation, metrics,
and other utility functions that support the core event system.
"""

from abc import ABC, abstractmethod
from typing import (
    Any,
    Dict,
    List,
    Optional,
    TypeVar,
    Generic,
    Iterator,
)

from continuallearning.events.core.event_types import EventType, BaseEventData

# Type variables
E = TypeVar("E", bound=BaseEventData)
T = TypeVar("T")


# ========== Event Storage and Persistence Interfaces ==========


class EventSerializerInterface(ABC, Generic[E]):
    """Interface for event serializers that can convert events to/from different formats."""

    @abstractmethod
    def serialize(self, event: E) -> Dict[str, Any]:
        """
        Serialize an event to a dictionary.

        Args:
            event: The event to serialize

        Returns:
            Serialized event data
        """
        pass

    @abstractmethod
    def deserialize(self, data: Dict[str, Any]) -> E:
        """
        Deserialize event data from a dictionary.

        Args:
            data: The serialized event data

        Returns:
            The deserialized event
        """
        pass

    @abstractmethod
    def supports_event_type(self, event_type: EventType) -> bool:
        """
        Check if this serializer supports the given event type.

        Args:
            event_type: The event type to check

        Returns:
            True if this serializer supports the event type
        """
        pass


class EventStoreInterface(ABC, Generic[E]):
    """Interface for event storage and retrieval."""

    @abstractmethod
    def store_event(self, event: E) -> str:
        """Store an event and return its identifier."""
        pass

    @abstractmethod
    def retrieve_event(self, event_id: str) -> Optional[E]:
        """Retrieve an event by its identifier."""
        pass

    @abstractmethod
    def query_events(
        self,
        event_type: Optional[EventType] = None,
        start_time: Optional[float] = None,
        end_time: Optional[float] = None,
        limit: Optional[int] = None,
    ) -> Iterator[E]:
        """Query events based on criteria."""
        pass

    @abstractmethod
    def delete_event(self, event_id: str) -> bool:
        """Delete an event from storage."""
        pass


class EventArchiveInterface(ABC, Generic[E]):
    """Interface for long-term event archiving."""

    @abstractmethod
    def archive_events(
        self,
        events: List[E],
        archive_name: str,
        metadata: Optional[Dict[str, Any]] = None,
    ) -> str:
        """Archive a collection of events."""
        pass

    @abstractmethod
    def restore_events(self, archive_id: str) -> List[E]:
        """Restore events from an archive."""
        pass

    @abstractmethod
    def list_archives(self) -> List[Dict[str, Any]]:
        """List available archives with metadata."""
        pass


# ========== Monitoring and Observability Interfaces ==========


class EventObserverInterface(ABC, Generic[E]):
    """
    Interface for event observers that monitor events without modifying them.

    Observers are useful for logging, metrics collection, and debugging.
    """

    @abstractmethod
    def observe(self, event: E) -> None:
        """
        Observe an event without modifying it.

        Args:
            event: The event to observe
        """
        pass

    @abstractmethod
    def get_observed_events(self) -> List[EventType]:
        """
        Return the list of event types this observer monitors.

        Returns:
            List of event types
        """
        pass

    @property
    @abstractmethod
    def observer_name(self) -> str:
        """Name of this observer for identification."""
        pass


class EventMetricsInterface(ABC):
    """Interface for collecting and reporting event metrics."""

    @abstractmethod
    def record_event(self, event: BaseEventData) -> None:
        """Record an event for metrics tracking."""
        pass

    @abstractmethod
    def get_event_count(self, event_type: Optional[EventType] = None) -> int:
        """Get the count of events, optionally filtered by type."""
        pass

    @abstractmethod
    def get_processing_time_stats(
        self, event_type: Optional[EventType] = None
    ) -> Dict[str, float]:
        """Get processing time statistics."""
        pass

    @abstractmethod
    def get_throughput_stats(
        self, time_window_seconds: float = 60.0
    ) -> Dict[str, float]:
        """Get throughput statistics for a time window."""
        pass

    @abstractmethod
    def reset_metrics(self) -> None:
        """Reset all collected metrics."""
        pass


class EventLoggerInterface(ABC):
    """Interface for event logging."""

    @abstractmethod
    def log_event(self, event: BaseEventData, level: str = "INFO") -> None:
        """Log an event with the specified level."""
        pass

    @abstractmethod
    def log_error(self, event: BaseEventData, error: Exception) -> None:
        """Log an event processing error."""
        pass

    @abstractmethod
    def set_log_level(self, level: str) -> None:
        """Set the logging level."""
        pass


# ========== Configuration and Registration Interfaces ==========


class ComponentRegistryInterface(ABC, Generic[T]):
    """Interface for component registration and discovery."""

    @abstractmethod
    def register(self, name: str, component: T, version: str = "1.0.0") -> None:
        """
        Register a component with a name and version.

        Args:
            name: Component name
            component: The component instance
            version: Component version
        """
        pass

    @abstractmethod
    def get(self, name: str, version: Optional[str] = None) -> Optional[T]:
        """
        Get a registered component.

        Args:
            name: Component name
            version: Optional version (latest if not specified)

        Returns:
            The component instance or None if not found
        """
        pass

    @abstractmethod
    def list_available(self) -> Dict[str, List[str]]:
        """
        List all available components and their versions.

        Returns:
            Dictionary mapping component names to available versions
        """
        pass

    @abstractmethod
    def unregister(self, name: str, version: Optional[str] = None) -> bool:
        """Unregister a component."""
        pass


class ConfigurationInterface(ABC):
    """Interface for event system configuration."""

    @abstractmethod
    def get_config(self, key: str, default: Any = None) -> Any:
        """
        Get a configuration value.

        Args:
            key: Configuration key
            default: Default value if key not found

        Returns:
            Configuration value
        """
        pass

    @abstractmethod
    def set_config(self, key: str, value: Any) -> None:
        """
        Set a configuration value.

        Args:
            key: Configuration key
            value: Configuration value
        """
        pass

    @abstractmethod
    def load_from_dict(self, config_dict: Dict[str, Any]) -> None:
        """
        Load configuration from a dictionary.

        Args:
            config_dict: Configuration dictionary
        """
        pass

    @abstractmethod
    def to_dict(self) -> Dict[str, Any]:
        """
        Export configuration as a dictionary.

        Returns:
            Configuration dictionary
        """
        pass

    @abstractmethod
    def validate_config(self) -> List[str]:
        """
        Validate the current configuration.

        Returns:
            List of validation errors (empty if valid)
        """
        pass


# ========== Event Factory Interfaces ==========


class EventFactoryInterface(ABC, Generic[E]):
    """Interface for creating events."""

    @abstractmethod
    def create_event(
        self,
        event_type: EventType,
        data: Dict[str, Any],
        metadata: Optional[Dict[str, Any]] = None,
    ) -> E:
        """Create an event of the specified type."""
        pass

    @abstractmethod
    def supports_event_type(self, event_type: EventType) -> bool:
        """Check if this factory can create the given event type."""
        pass

    @abstractmethod
    def get_supported_event_types(self) -> List[EventType]:
        """Get all event types this factory can create."""
        pass
